<?php

/**
 * @Author: RainLee <rainlee1990@yeah.net>
 * @Date: 2022-01-10 22:38:52
 * @LastEditors: RainLee <rainlee1990@yeah.net>
 * @LastEditTime: 2022-02-21 21:47:53
 * @Description: 文件说明
 */

namespace rainlee\auth\guard;

use rainlee\auth\provider\CreateUserProviders;
use rainlee\auth\Recaller;
use think\facade\Cookie;
use think\facade\Session;
use rainlee\auth\Authenticatable;
use think\helper\Str;

class JwtGuard
{
    use CreateUserProviders;

    protected $provider = null;

    protected $guardName;

    protected $user = null;

    protected $recallAttempted = false;


    public function __construct($name, $config)
    {
        $this->guardName = $name;
        $this->provider = $this->createUserProviders($config['provider']);
    }

    /**
     * 尝试登录
     *
     * @param  array  $credentials
     * @param  bool   $remember
     * @return bool
     */
    public function attempt(array $credentials = [])
    {
        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
        if (!is_null($user) && $this->hasValidCredentials($user, $credentials)) {
            return $this->login($user);
        }

        return false;
    }

    /**
     * 尝试通过ID登录
     * 
     * @param int $id
     * @param bool $remember
     * @return bool
     */
    public function attemptById($id)
    {
        if (!is_null($user = $this->provider->retrieveById($id))) {
            return $this->login($user);
        }
        return false;
    }

    /**
     * 验证参数有效性
     * 
     * @param \rainlee\auth\Authenticatable|null $user 用户对象
     * @param array $credentials 参数
     * @return bool
     */
    protected function hasValidCredentials($user, $credentials)
    {
        return !is_null($user) && $this->provider->validatePassword($user, $credentials['password']);
    }

    /**
     * 登录操作
     * 
     * @param \rainlee\auth\Authenticatable $user 用户对象
     * @param bool $remember
     * @return void
     */
    protected function login(Authenticatable $user)
    {

        $this->setUser($user);
    }

    /**
     * 创建Token
     * 
     */
    protected function createToken(Authenticatable $user)
    {
    }

    /**
     * 获取用户信息
     */
    public function user()
    {
        // 用户存在则只接返回用户信息
        if (!is_null($this->user)) {
            return $this->user;
        }



        return $this->user;
    }

    /**
     * 通过remember token获取用户信息
     *
     * @param  \rainlee\auth\Recaller $recaller
     * @return mixed
     */
    protected function userFromRecaller($recaller)
    {
        if (!$recaller->valid() || $this->recallAttempted) {
            return;
        }

        $this->recallAttempted = true;

        $this->viaRemember = !is_null($user = $this->provider->retrieveByRememberToken(
            $recaller->id(),
            $recaller->token()
        ));

        return $user;
    }


    /**
     * 验证用户是否登录
     *
     * @return bool
     */
    public function check()
    {
        return !is_null($this->user());
    }

    /**
     * 获取客户端IP地址
     * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
     * @param boolean $adv 是否进行高级模式获取（有可能被伪装） 
     * @return mixed
     */
    protected function getClientIp($type = 0, $adv = true)
    {
        $type =  $type ? 1 : 0;
        $ip   =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if ($adv) {
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos    =   array_search('unknown', $arr);
                if (false !== $pos) unset($arr[$pos]);
                $ip     =   trim($arr[0]);
            } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip     =   $_SERVER['HTTP_CLIENT_IP'];
            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip     =   $_SERVER['REMOTE_ADDR'];
            }
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip     =   $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u", ip2long($ip));
        $_SERVER['REMOTE_PORT'] && $ip .= ':' . $_SERVER['REMOTE_PORT'];
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }

    /**
     * 设置当前用户
     * 
     * @param \rainlee\auth\Authenticatable $user
     * @return void
     */
    protected function setUser(Authenticatable $user)
    {
        $this->user = $user;
    }
}
